package model.semantics;

import java.util.*;

import util.reflection.Reflection;

import model.State;


/**
 * Represents an operator within the expression tree.
 * @author Sterling Dorminey
 *
 */
public class OperatorNode<T> extends Node<T> {
	private Node<T>[] myChildren;
	private Operation<T> myOperation;
	
	/**
	 * Create a node with the children and the operation to do on the children.
	 * @param operation the operation to perform.
	 * @param values the children to perform it on.
	 */
	public OperatorNode(Operation<T> operation, Node<T> ... values) {
		myChildren = Arrays.copyOf(values, values.length);
		myOperation = operation;
	}
	
	/**
	 * Produce a color by evaluating the children.
	 * @param x the x-coordinate.
	 * @param y the y-coordinate.
	 * @return the color.
	 */
	@Override
	@SuppressWarnings("unchecked")
	public T evaluate(State<T> state) {
		List<T> values = new ArrayList<T>(myChildren.length);
		for(int i = 0; i < myChildren.length; i++) {
			values.add(myChildren[i].evaluate(state));
		}
		return myOperation.evaluate(state, (T [])values.toArray());
	}
	
	/**
	 * Does a preorder traversal of the expression tree to print a string for the tree.
	 */
	@Override
	public String toString() {
		// Get string for argument list.
		StringBuilder sb = new StringBuilder();
		for(int i = 0; i < myChildren.length-1; i++) {
			sb.append(myChildren[i].toString() + ", ");
		}
		sb.append(myChildren[myChildren.length-1].toString());
		
		return String.format("%s(%s)", myOperation.getClass().getName().toString(), sb.toString());
	}
}
